﻿using System;
using System.Collections.Generic;
using Infraestrutura.Repositorios.SQL;
using System.Configuration;
using System.Data.SqlClient;

namespace Model.Clientes
{
    public class ClienteService: RepositorioSQL<Cliente>, IClienteService
    {
        public ClienteService()
        {
            Tabela = "Clientes";
            LigacaoBD = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
        }

        public Cliente ObterPorIdCliente(Int64 idCliente)
        {
            return ObterPorChave(String.Format("@IdCliente={0}", idCliente));
        }

        public Unidade ObterUnidadePorIdUnidade(Int64 idUnidade)
        {
            Unidade item = null;

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_UnidadesLoadByPrimaryKey @IdUnidade={0}", idUnidade),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    item = new Unidade();
                    item = CarregarDadosUnidade(reader, item);
                }

                reader.Close();

                Cliente cliente = ObterPorIdCliente(item.Cliente.IdCliente);
                item.Cliente = cliente;
            }
            
            return item;
        }

        public IList<Unidade> ObterUnidadesPorCliente(Cliente cliente)
        {
            return ObterUnidadesPorCliente(cliente.IdCliente);
        }

        public IList<Unidade> ObterUnidadesPorCliente(Int64 idCliente)
        {
            IList<Unidade> lista = new List<Unidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_UnidadesLoadByIdCliente @IdCliente={0}", idCliente),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                Unidade item = null;
                while (reader.Read())
                {
                    item = new Unidade();
                    lista.Add(CarregarDadosUnidade(reader, item));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<Unidade> ObterUnidadesTopoPorCliente(Cliente cliente)
        {
            return ObterUnidadesTopoPorCliente(cliente.IdCliente);
        }

        public IList<Unidade> ObterUnidadesTopoPorCliente(Int64 idCliente)
        {
            IList<Unidade> lista = new List<Unidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_UnidadesTopoLoadByIdCliente @IdCliente={0}", idCliente),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                Unidade item = null;
                while (reader.Read())
                {
                    item = new Unidade();
                    lista.Add(CarregarDadosUnidade(reader, item));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<Unidade> ObterUnidadesContratoPorCliente(Cliente cliente)
        {
            return ObterUnidadesContratoPorCliente(cliente.IdCliente);
        }

        public IList<Unidade> ObterUnidadesContratoPorCliente(Int64 idCliente)
        {
            IList<Unidade> lista = new List<Unidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_UnidadesComContratoLoadByCliente  @IdCliente={0}", idCliente),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                Unidade item = null;
                while (reader.Read())
                {
                    item = new Unidade();
                    lista.Add(CarregarDadosUnidade(reader, item));
                }

                reader.Close();
            }

            return lista;
        }


        public IList<Unidade> ObterUnidadesServicoPorCliente(Cliente cliente)
        {
            IList<Unidade> lista = new List<Unidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_UnidadesServicoLoadByIdCliente @IdCliente={0}", cliente.IdCliente),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                Unidade item = null;
                while (reader.Read())
                {
                    item = new Unidade();
                    lista.Add(CarregarDadosUnidade(reader, item, cliente));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<Unidade> ObterUnidadesFilhoPorUnidadePai(Unidade unidadePai)
        {
            
            IList<Unidade> lista = new List<Unidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_UnidadesFilhoLoadByIdUnidade {0}", unidadePai.IdUnidade),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                Unidade item = null;
                while (reader.Read())
                {
                    item = new Unidade();
                    lista.Add(CarregarDadosUnidade(reader, item, unidadePai));
                }

                reader.Close();
            }

            return lista;
        }


        public Unidade Actualiza(Unidade item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_UnidadesUpdate {0}", ObterParametrosActualizar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteScalar();
            }

            return item;
        }

        public Unidade Insere(Unidade item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_UnidadesInsert {0}", ObterParametrosInserir(item)),
                    connection);

                command.Connection.Open();
                item.AtribuirChave(command.ExecuteScalar());
            }

            return item;
        }

        public void Apaga(Unidade item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_UnidadesDelete {0}", ObterParametrosApagar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }

        
        #region Metodos de Carregamento de Dados e Parametros
        
        protected override String ObterParametrosInserir(Cliente item)
        {
            return String.Format("@IdCliente={0}, @Nome='{1}'",
                                   item.IdCliente, item.Nome);
        }

        protected override String ObterParametrosApagar(Cliente item)
        {
            return String.Format("@IdCliente={0}",
                                  item.IdCliente);
        }

        protected String ObterParametrosInserir(Unidade item)
        {
            if(item.UnidadePai != null)
                return String.Format("@IdUnidade={0}, @IdCliente={1}, @UnidadePai={2}, @Designacao='{3}', @Servico={4}",
                                   item.IdUnidade, item.Cliente.IdCliente, item.UnidadePai.IdUnidade,
                                   item.Designacao, item.Servico);
            else
                return String.Format("@IdUnidade={0}, @IdCliente={1}, @Designacao='{2}', @Servico={3}",
                                   item.IdUnidade, item.Cliente.IdCliente, item.Designacao, item.Servico);
        }

        protected String ObterParametrosActualizar(Unidade item)
        {
            return ObterParametrosInserir(item);
        }


        protected String ObterParametrosApagar(Unidade item)
        {
            return String.Format("@IdUnidade={0}",
                                  item.IdUnidade);
        }


        protected override Cliente CarregarDados(SqlDataReader dataReader, Cliente item)
        {
            item.IdCliente = Convert.ToInt64(dataReader["IdCliente"]);
            item.Nome = dataReader["Nome"].ToString();
            
            return item;
        }

        private Unidade CarregarDadosUnidade(SqlDataReader dataReader, Unidade item)
        {
            item.Cliente = new Cliente() { IdCliente = Convert.ToInt64(dataReader["IdCliente"]), 
                                           Nome = dataReader["NomeCliente"].ToString() };
            item.IdUnidade = Convert.ToInt64(dataReader["IdUnidade"]);
            item.Designacao = Convert.ToString(dataReader["Designacao"]);
            item.Servico = Convert.ToBoolean(dataReader["Servico"]);

            if (!Convert.IsDBNull(dataReader["UnidadePai"]))
            {
                item.UnidadePai = new Unidade();
                item.UnidadePai.IdUnidade = Convert.ToInt64(dataReader["UnidadePai"]);
                item.UnidadePai.Designacao = dataReader["DesignacaoPai"].ToString();
                item.UnidadePai.Servico = Convert.ToBoolean(dataReader["ServicoPai"]);
                item.UnidadePai.Cliente = item.Cliente;
                if (!Convert.IsDBNull(dataReader["UnidadePaiPai"]))
                    item.UnidadePai.UnidadePai = new Unidade() { IdUnidade = Convert.ToInt64(dataReader["UnidadePaiPai"]) };
            }
            return item;
        }

        private Unidade CarregarDadosUnidade(SqlDataReader dataReader, Unidade item, Cliente cliente)
        {
            item.Cliente = cliente;
            item.IdUnidade = Convert.ToInt64(dataReader["IdUnidade"]);
            item.Designacao = Convert.ToString(dataReader["Designacao"]);
            item.Servico = Convert.ToBoolean(dataReader["Servico"]);
            item.UnidadePai = null;

            return item;
        }

        private Unidade CarregarDadosUnidade(SqlDataReader dataReader, Unidade item, Unidade unidadePai)
        {
            item.Cliente = unidadePai.Cliente;
            item.IdUnidade = Convert.ToInt64(dataReader["IdUnidade"]);
            item.Designacao = Convert.ToString(dataReader["Designacao"]);
            item.Servico = Convert.ToBoolean(dataReader["Servico"]);
            item.UnidadePai = unidadePai;

            return item;
        }

        #endregion
    }
}
